import React from "react";

export default class LearnSetState extends React.Component {
  constructor() {
    super();
    /**
     * 定义当前组件的state
     * 这个对象里面可以存放任意数据
     * 并且里面的数据修改会（setState），视图会重新然选
     */
    // this.state = {
    //   name: "张三",
    // };
  }

  /**
   * 直接在组件内部定义属性
   * 一般来说，定义state的时候，都是直接在组件内部直接定义
   * 如果说在constructor中已经定义过state属性的话
   * 会覆盖组件内的state，也就是说 constructor 中定义的state属性
   * 优先级最好
   */
  state = {
    name: "李四",
    age: 10,
    num: 1,
    arr: [
      {
        name: "张三",
        age: 20,
      },
      {
        name: "李四",
        age: 25,
      },
    ],
    info: {
      name: "王凯",
      age: 20,
    },
  };

  add() {
    /**
     * 直接通过this.state.xx = xx的方式修改
     * 视图层不会改变，也就是不会重新渲染
     * 那么数据层，会改变
     */
    // this.state.num += 1;
    // console.log(this.state.num)

    /**
     * setState第一个参数为函数
     * 那么该函数会接收两个参数
     *
     * preState state更新前的值
     * props 组件接收的参数（
     * 这里的props还没有讲，等到组件传值的时候
     * 会在详细讲一下
     * ）
     * 这个函数必须有返回值，
     * 返回的值就是要更新state的值
     */
    // this.setState((preState, prosp) => {
    //   console.log(preState)
    //   /**
    //    * return 一个对象
    //    * 这个对象会合当前的state做一个合并的操作
    //    * 并修改state，视图会重新渲染
    //    */
    //   return {
    //     num: preState.num + 1
    //   }
    // })

    /**
     * 传入一个对象
     * 这个对象里面存放的就是要修改state的数据
     * 这也是最常用的修改方式
     */
    this.setState({
      /**
       * 当前的this 指向 当前组件
       * 所以我们可以拿到更新前的state
       */
      num: this.state.num + 1,
      age: 30,
      name: "赵六",
    });
  }

  pushArr() {
    /**
     * this.setState 是异步的
     * 所以在下一行拿不到最新的值
     * 可以使用setState的第二个参数 来获取最新的值
     */
    // this.setState({
    //   /**
    //    * 使用es 6数组结构的形式进行添加
    //    */
    //   arr: [...this.state.arr, { name: "王凯", age: 30 }],

    //   /**
    //    * 第二个参数是一个回调函数
    //    * 在里面可以拿到state最新的值
    //    * 注意：
    //    * 第二个参数一般来说都是使用箭头函数来编写
    //    * 该函数会在render后触发
    //    *
    //    */
    // }, () => {
    //   console.log(this.state.arr, '箭头函数里面的')
    // });
    // console.log("箭头函数外面的")

    /**
     * 先获取到当前的数据
     * 然后对当前的数据进行操作
     * 但是，这么视图不会重新渲染
     */
    this.state.arr.push({ name: "王凯", age: 30 });

    /**
     * 修改完成后，需要手动的setState渲染视图
     */
    this.setState(
      {
        arr: this.state.arr,
      },
      () => {
        console.log(this.state.arr);
      }
    );
  }

  updateInfo () {
    this.setState({
      /**
       * 使用对象解构的方式进行修改
       * 注意：要把对象里面之前的数据放进来
       * 否则会丢失
       * 如果更新的对象巨大，那么就要考虑别的方式更新
       * 这方面等讲到不可变数据的时候会详细讲
       */
      info: {
        ...this.state.info,
        name: "赵六"
      }
    })
  }

  /**
   * 所谓的视图渲染 就是重新调用render函数
   * @returns
   */
  render() {
    console.log("渲染~~~");
    return (
      <div>
        <div>我是组件的state</div>
        {/* 
          通过this直接指向当前组件实例
          在组件实例里面我们定义了一个state对象
          就可以取里面的值
        */}
        <div>
          {this.state.name} -- {this.state.age}
        </div>

        {this.state.num}
        <button onClick={() => this.add()}>+1</button>
        <button onClick={() => this.pushArr()}>往数组里面添加数据</button>
        <div>
          <div>
            info对象{this.state.info.name} --- {this.state.info.age}
          </div>
          <button onClick={() => this.updateInfo()}>更新info</button>
        </div>
      </div>
    );
  }
}
